package com.jumi.microservice.order.handler;

import com.alibaba.fastjson.JSON;
import com.jumi.microservice.enumerate.OrderTypeEnum;
import com.jumi.microservice.order.context.GoodsSkuContext;
import com.jumi.microservice.order.context.OrderCreateContext;
import com.jumi.microservice.order.context.TransHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Dirk
 * @Date 2020-08-11 14:19
 */
@Component
public class SplitOrderHandler implements TransHandler {

    private static final Logger log = LoggerFactory.getLogger(TransHandler.class);

    @Override
    public boolean isAsync() {
        return false;
    }

    @Override
    public boolean handler(TransHandlerContext context) {
        OrderCreateContext ctx = (OrderCreateContext) context;
        log.info("未拆单时上下文参数: [{}]", JSON.toJSONString(ctx));
        List<GoodsSkuContext> goodsSkuContextList = ctx.getGoodsList();
        List<OrderCreateContext> childOrderContext = new ArrayList<>();
        // 预售商品拆单
        Iterator<GoodsSkuContext> iterator = goodsSkuContextList.iterator();
        while (iterator.hasNext()) {
            GoodsSkuContext goodsSkuContext = iterator.next();
            if (goodsSkuContext.getIsPre().equals(1)) {
                List<GoodsSkuContext> goodsList = new ArrayList<>();
                goodsList.add(goodsSkuContext);
                OrderCreateContext orderCreateContext = createChildOrderContext(ctx, goodsList);
                orderCreateContext.setOrderType(OrderTypeEnum.PRE_SALE_CREATE.getCode());
                childOrderContext.add(orderCreateContext);
                iterator.remove();
            }
        }

        // 自营拆单
        iterator = goodsSkuContextList.iterator();
        List<GoodsSkuContext> selfGoodsList = new ArrayList<>();
        while (iterator.hasNext()) {
            GoodsSkuContext goodsSkuContext = iterator.next();
            if (goodsSkuContext.getSelfFlag().equals(new Byte("1"))) {
                selfGoodsList.add(goodsSkuContext);
                iterator.remove();
            }
        }
        if (!selfGoodsList.isEmpty()) {
            OrderCreateContext orderCreateContext = createChildOrderContext(ctx, selfGoodsList);
            childOrderContext.add(orderCreateContext);
        }

        // 非自营按供应商拆单
        Set<Integer> supplierIds = goodsSkuContextList.stream()
                .map(GoodsSkuContext::getSupplierId).collect(Collectors.toSet());
        for (Integer supplierId : supplierIds) {
            childOrderContext.add(createChildOrderContext(ctx, goodsSkuContextList.stream()
                    .filter(goodsSkuContext -> supplierId.equals(goodsSkuContext.getSupplierId()))
                    .collect(Collectors.toList())));
        }

        ctx.setChildOrderContextList(childOrderContext);
        return true;
    }

    private OrderCreateContext createChildOrderContext(OrderCreateContext ctx, List<GoodsSkuContext> goodsList) {
        OrderCreateContext orderCreateContext = new OrderCreateContext();
        BeanUtils.copyProperties(ctx, orderCreateContext);
        orderCreateContext.setGoodsList(goodsList);

        orderCreateContext.setOrderPromotionAmount(orderCreateContext.getGoodsList().stream()
                .map(goodsSkuContext -> goodsSkuContext.getGoodsPromotionPrice()
                        .multiply(new BigDecimal(goodsSkuContext.getGoodsAmount())))
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        orderCreateContext.setOrderAmount(orderCreateContext.getGoodsList().stream()
                .map(goodsSkuContext -> goodsSkuContext.getGoodsPrice()
                        .multiply(new BigDecimal(goodsSkuContext.getGoodsAmount())))
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        orderCreateContext.setFreightFee(orderCreateContext.getGoodsList().stream()
                .map(GoodsSkuContext::getGoodsFreightFee)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        orderCreateContext.setPayAmount(orderCreateContext.getOrderAmount()
                .add(orderCreateContext.getFreightFee()));
        return orderCreateContext;
    }
}
